package com.tc.property.spring;

import com.tc.property.PropertyHolder;
import com.tc.property.impl.PropertyManagerImpl;
import com.tc.property.support.PropertiesUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.beans.factory.config.RuntimeBeanNameReference;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;


public class TcPropertyPlaceholderBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
	private static final String SYSTEM_PROPERTIES_MODE_ATTRIB = "system-properties-mode";
	private static final String SYSTEM_PROPERTIES_MODE_DEFAULT = "ENVIRONMENT";

	private static Logger LOGGER = LoggerFactory.getLogger(TcPropertyPlaceholderBeanDefinitionParser.class);

	//PropertyChangedHandler
	private ManagedList<Object> handlersRef = new ManagedList<Object>();

	@Override
	protected Class<?> getBeanClass(Element element) {
		if (element.getAttribute(SYSTEM_PROPERTIES_MODE_ATTRIB).equals(SYSTEM_PROPERTIES_MODE_DEFAULT)) {
			return TcPropertySourcesPlaceholderConfigurer.class;
		}
		return PropertyPlaceholderConfigurer.class;
	}
	
	@Override
	protected void doParse(Element element, BeanDefinitionBuilder builder) {
		/**
		 * 支持spring-context
		 */
		super.doParse(element, builder);
		/**
		 * init all props
		 */
		PropertiesUtils.getPropsConfig(element);
		PropertyHolder.getProperties().put("abc", "hello word spring properties");
	}
	
	@Override
	protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {//spring启动加载
		this.doParse(element, builder);
		this.resolveHandlers(element, parserContext);
		RootBeanDefinition propertyManager = new RootBeanDefinition(PropertyManagerImpl.class);
		propertyManager.getPropertyValues().add("handlers", handlersRef);
		parserContext.getRegistry().registerBeanDefinition("propertyManager", propertyManager);
	}

	/**
	 * 解析handlers
	 */
	private void resolveHandlers(Element element, ParserContext parserContext) {
		NodeList nodeList = element.getChildNodes();
		if (nodeList != null && nodeList.getLength() > 0) {
			for (int i = 0; i < nodeList.getLength(); i++) {
				Node node = nodeList.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					if (ele.getTagName().endsWith("property-handlers")) {
						NodeList handlerList = ele.getChildNodes();
						if (handlerList != null && handlerList.getLength() > 0) {
							for (int j = 0; j < handlerList.getLength(); j++) {
								Node handler = handlerList.item(j);
								if (handler instanceof Element) {
									Element beanEle = (Element) handler;
									if (beanEle.getTagName().endsWith("bean")) {
										BeanDefinitionHolder beanDefHolder = parserContext.getDelegate()
												.parseBeanDefinitionElement(beanEle);
										handlersRef.add(beanDefHolder.getBeanDefinition());
									} else if (beanEle.getTagName().endsWith("ref")) {
										Object refObj = parserContext.getDelegate().parseIdRefElement(beanEle);
										RuntimeBeanNameReference nameRef = (RuntimeBeanNameReference) refObj;

										RuntimeBeanReference beanRef = new RuntimeBeanReference(nameRef.getBeanName());
										beanRef.setSource(nameRef.getSource());
										handlersRef.add(beanRef);
									}
								}
							}
						}
					}
				}
			}
		}
	}

	@Override
	protected boolean shouldGenerateId() {
		return true;
	}
	
	
}
